﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using mfe.bll;
using mshtml;
using System.IO;
using System.Collections.Specialized;
using System.Security;
using System.Security.Permissions;
using System.Reflection;

namespace mfe_proj.Forms
{
    /// <summary>
    /// 1/26/2009, leyang
    /// ContentViewer is the form that hosts a webbrowser control, this control will be responsible for displaying the content of each item.
    /// When each item is created, the content composed of html will be saved to the database. Since this webbrowser is an embedded control,
    /// it will not support the conventional navigation model, mainly for the purpose of cross referencing, we cannot use pure html link that
    /// points to a physical html page. For that, we use the ObjectForscripting that allow us to embed some javascript calls in the content,
    /// while it can also communicate with the host form. This should enable us to click on a link on the content viewer and load the content
    /// of that item.
    /// </summary>
    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    [System.Runtime.InteropServices.ComVisibleAttribute(true)]
    public partial class ContentViewer : Form
    {
        string scriptPath;
        private IHTMLDocument2 doc;
        string _ItemGuidID;
        public string ItemGuidID { get { return _ItemGuidID; } set { _ItemGuidID = value; } }

        public ContentViewer()
        {
            InitializeComponent();

            webBrowser1.DocumentText = "<html><body></body></html>";
            webBrowser1.ObjectForScripting = this;
            doc = webBrowser1.Document.DomDocument as IHTMLDocument2;

            //write out the jquery-1.3.1.min.js script file to a temp folder.
            scriptPath = string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "\\mfe\\Scripts\\");
            if (!System.IO.File.Exists(scriptPath + "jquery-1.3.1.min.js"))
            {
                if (!System.IO.Directory.Exists(scriptPath)) System.IO.Directory.CreateDirectory(scriptPath);
                Assembly assembly = Assembly.GetExecutingAssembly();
                using (Stream stream = assembly.GetManifestResourceStream("mfe_proj.Scripts.jquery-1.3.1.min.js"))
                {
                    using (StreamReader streamReader = new StreamReader(stream))
                    {
                        using (TextWriter tw = new StreamWriter(scriptPath + "jquery-1.3.1.min.js"))
                        {
                            tw.Write(streamReader.ReadToEnd());
                        }
                    }
                }
            }
        }

        public void LoadStartPage()
        {
            doc.write("");
            doc.close();
            doc.writeln("<html><head>");
            //doc.writeln("<script type=\"text/javascript\" src=\"" + scriptPath + "jquery-1.3.1.min.js\"></script>");
            //doc.writeln("<style type=\"text/css\">table{font-size: 10pt;}h3{color:#600000 } div{font-size: 10pt;}a:visited{text-decoration: none;font-size: 10pt;color: #0033CC;}a:link {text-decoration:none;font-size: 10pt;color:#0033CC;}a:active { text-decoration: none;color:#0033CC;font-size: 10pt; } a:hover{color: #FFFFFF;font-size: 10pt;background-color: #000080;}</style>");
            //doc.writeln("<script type=\"text/javascript\">");
            //doc.writeln("$(function(e){");
            //doc.writeln("   $('#divInfo').hide();");
            //doc.writeln("   $('#linkInfo').click(function(e){");
            //doc.writeln("       $('#divInfo').show('fast');");
            //doc.writeln("   });");
            //doc.writeln("});");
            //doc.writeln("</script>");
            doc.writeln("</head><body>");
            doc.writeln("<h1>Welcome to MFE!</h1>");
            doc.writeln("</body></html>");
        }

        public void LoadItem(string itemGuidID)
        {
            ///TODO: disable clicking sound in the browser, maybe look at the mozilla activex control?
            ///or use webBrowser1.Document.Write()?
            Item a = new Item(itemGuidID);
            StringCollection fields = new StringCollection();
            StringCollection conditions = new StringCollection();
            fields.Add("PhotoGuidID");
            fields.Add("Title");
            fields.Add("Caption");
            fields.Add("Thumbnail");
            conditions.Add(string.Concat("ItemGuidID='", itemGuidID, "'"));
            List<Photo> photos = null;
            string dirpath = string.Empty;
            if (a.ShowPhoto)
            {
                photos = Photo.PhotoCollection(fields, conditions);
                //save photo to temp folder
                dirpath = string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "\\mfe\\images\\");
                if (!System.IO.Directory.Exists(dirpath)) System.IO.Directory.CreateDirectory(dirpath);
                foreach (Photo photo in photos)
                {
                    using (MemoryStream ms = new MemoryStream(photo.Thumbnail))
                    {
                        Image img = Image.FromStream(ms);
                        img.Save(string.Concat(dirpath, photo.PhotoGuidID, ".jpg"), System.Drawing.Imaging.ImageFormat.Jpeg);
                    }
                }
            }
            doc.write("");
            doc.close();
            doc.writeln("<html><head>");
            doc.writeln("<script type=\"text/javascript\" src=\"" + scriptPath + "jquery-1.3.1.min.js\"></script>");
            doc.writeln("<style type=\"text/css\">table{font-size: 10pt;}h3{color:#600000 } div{font-size: 10pt;}a:visited{text-decoration: none;font-size: 10pt;color: #0033CC;}a:link {text-decoration:none;font-size: 10pt;color:#0033CC;}a:active { text-decoration: none;color:#0033CC;font-size: 10pt; } a:hover{color: #FFFFFF;font-size: 10pt;background-color: #000080;}</style>");
            doc.writeln("<script type=\"text/javascript\">");
            doc.writeln("$(function(e){");
            doc.writeln("   $('#linkInfo').click(function(e){");
            doc.writeln("       $('#divInfo').show('fast');");
            doc.writeln("   });");
            doc.writeln("});");
            doc.writeln("</script>");
            doc.writeln("</head><body>");
            doc.writeln("<h3>" + a.Title + "</h3>");
            doc.writeln(SummaryInfo(a));
            doc.writeln("<table width=100% cellpadding=4 cellspacing=0 border=0>");
            doc.writeln("<tr>");
            if (photos != null && photos.Count > 0)
            {
                ///TODO: simplify this block
                #region show photo
                switch ((Enums.DefaultPhotoPos)a.DefaultPhotoPos)
                {
                    case Enums.DefaultPhotoPos.Left:
                        doc.writeln("<td valign=top>");
                        DisplayPhotos(doc, photos, dirpath, Enums.DefaultPhotoPos.Left);
                        doc.writeln("</td>");
                        doc.writeln("<td valign=top width=100%>");
                        doc.writeln(a.Content);
                        doc.writeln("</td></tr>");
                        break;
                    case Enums.DefaultPhotoPos.Top:
                        doc.writeln("<td valign=top>");
                        DisplayPhotos(doc, photos, dirpath, Enums.DefaultPhotoPos.Top);
                        doc.writeln("</td></tr><tr>");
                        doc.writeln("<td height=20px></td><tr>");
                        doc.writeln("<td valign=top>");
                        doc.writeln(a.Content);
                        doc.writeln("</td></tr>");
                        break;
                    case Enums.DefaultPhotoPos.Right:
                        doc.writeln("<td valign=top width=100%>");
                        doc.writeln(a.Content);
                        doc.writeln("</td>");
                        doc.writeln("<td valign=top>");
                        DisplayPhotos(doc, photos, dirpath, Enums.DefaultPhotoPos.Right);
                        doc.writeln("</td></tr>");
                        break;
                    case Enums.DefaultPhotoPos.Bottom:
                        doc.writeln("<td valign=top>");
                        doc.writeln(a.Content);
                        doc.writeln("</td></tr><tr>");
                        doc.writeln("<td height=20px></td><tr>");
                        doc.writeln("<td valign=top>");
                        DisplayPhotos(doc, photos, dirpath, Enums.DefaultPhotoPos.Bottom);
                        doc.writeln("</td></tr>");
                        break;
                }
                #endregion
            }
            else
            {
                doc.writeln("<td valign=top>");
                doc.writeln(a.Content);
                doc.writeln("</td></tr>");
            }
            
            doc.writeln("</table>");
            //doc.writeln(DisplayCharactorsAndWorks(a));
            doc.writeln(MagazineContent(a));
            doc.writeln(DisplayRelatedItem(a));
            doc.writeln("</body></html>");
            doc.close();
        }

        string MagazineContent(Item item)
        {
            StringBuilder sb = new StringBuilder();
            if ((Enums.ContentType)item.ContentType == Enums.ContentType.Magazine)
            {
                StringCollection conditions = new StringCollection();
                conditions.Add("ItemGuidID='" + _ItemGuidID + "'");
                List<MagazineTOC> tocs = MagazineTOC.MagazineTOCCollection(null, conditions);
                if (tocs.Count > 0)
                {
                    sb.AppendLine("<hr size=1>");
                    sb.AppendLine("<table width=100% cellpadding=2 cellspacing=0 border=0>");
                    sb.AppendLine("<tr><td colspan=3><b>目录</b></td></tr>");
                    sb.AppendLine("<tr><td>Title</td><td>Author</td><td>Page</td></tr>");
                    //sb.AppendLine("<div><b>目录</b>");
                    //sb.AppendLine("<div>");
                    foreach (MagazineTOC toc in tocs)
                    {
                        sb.AppendLine("<tr>");
                        sb.AppendLine(string.Concat("<td>", toc.Title, "</td>"));
                        sb.AppendLine(string.Concat("<td>", toc.Author, "</td>"));
                        sb.AppendLine(string.Concat("<td>", toc.Page, "</td>"));
                        sb.AppendLine("</tr>");
                    }
                    sb.AppendLine("</table>");
                    //sb.AppendLine("</div></div>");
                }
            }

            return sb.ToString();
        }

        public void ShowPicture(string photoGuidID)
        {
            PhotoViewerForm pvForm = new PhotoViewerForm();
            pvForm.PhotoGuidID = photoGuidID;
            pvForm.ShowDialog();
        }

        void DisplayPhotos(IHTMLDocument2 doc, List<Photo> photos, string dirpath, Enums.DefaultPhotoPos pos)
        {
            foreach (Photo photo in photos)
            {
                doc.writeln("<span>");

                doc.writeln(string.Concat("<a href=javascript:void(0); onclick=\"window.external.ShowPicture('" + photo.PhotoGuidID + "')\"><img src=\"", dirpath, photo.PhotoGuidID + ".jpg\" border=0></a>"));
                if (pos == Enums.DefaultPhotoPos.Left || pos == Enums.DefaultPhotoPos.Right)
                {
                    doc.writeln("<div style=\"color=gray\">");
                    doc.writeln(photo.Title);
                    if (photo.Caption != null && photo.Caption.Length > 0)
                    {
                        doc.writeln(string.Concat(" - ", photo.Caption));
                    }
                }
                //doc.writeln("<button type=\"button\" id=\"btnClickMe\" value=\""+photo.PhotoGuidID+"\">Large image</button>");
                doc.writeln("</div>");
                doc.writeln("</span>");
                doc.writeln((pos == Enums.DefaultPhotoPos.Left || pos == Enums.DefaultPhotoPos.Right) ? "<BR><BR>" : "&nbsp;");
            }
        }

        string SummaryInfo(Item item)
        {
            //display a summary info in a block format.
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("<P><a href=\"javascript:void(0);\" id=\"linkInfo\">show</a></P>");
            sb.AppendLine("<div id=\"divInfo\" style=\"display:none;\">");
            sb.AppendLine("<table style=\"background-color=#eeeeee;width=100%;\" cellpadding=2 cellspacing=0 border=0>");
            if ((Enums.ContentType)item.ContentType == Enums.ContentType.Author ||
                (Enums.ContentType)item.ContentType == Enums.ContentType.Detective)
            {
                ItemPerson person = new ItemPerson(new Guid(item.ItemGuidID));
                Country country = new Country(person.CountryID);
                AssembleTableRow(sb, string.Concat("<b>", (Enums.ContentType)item.ContentType == Enums.ContentType.Author ? "作家" : "人物", "小资料</b>"));
                AssembleTableRow(sb, "国籍：" + country.Name);
                AssembleTableRow(sb, string.Concat("生卒：", person.DobYear > 0 ? person.DobYear.ToString() : "?", " - ", person.DodYear > 0 ? person.DodYear.ToString() : "?"));
                if (person.PenNames != null && person.PenNames.Length > 0)
                    AssembleTableRow(sb, "笔名：" + person.PenNames);
                if (person.ChineseNameReal != null && person.ChineseNameReal.Length > 0)
                    AssembleTableRow(sb, "真名：" + person.ChineseNameReal);
                if (person.AppearYear > 0)
                    AssembleTableRow(sb, "出道年：" + person.AppearYear.ToString());
                if (person.MainWork != null && person.MainWork.Length > 0)
                    AssembleTableRow(sb, "代表作：" + person.MainWork);
            }
            else if ((Enums.ContentType)item.ContentType == Enums.ContentType.Book)
            {
                ItemBook book = new ItemBook(new Guid(item.ItemGuidID));
                AssembleTableRow(sb, "<b>作品小资料</b>");
                if (book.ISBN10 != null && book.ISBN10.Length > 0)
                    AssembleTableRow(sb, "ISBN-10：" + book.ISBN10);
                if (book.ISBN13 != null && book.ISBN13.Length > 0)
                    AssembleTableRow(sb, "ISBN-13：" + book.ISBN13);
                if (book.PageCount > 0)
                    AssembleTableRow(sb, "页数：" + book.PageCount.ToString());
                if (book.Price != null && book.Price.Length > 0)
                    AssembleTableRow(sb, "定价：" + book.Price);
                if (book.PublishYear > 0)
                    AssembleTableRow(sb, string.Concat("出版日期：", book.PublishYear,
                        book.PublishMonth > 0 ? "/" + book.PublishMonth : "/?",
                        book.PublishDay > 0 ? "/" + book.PublishDay : ""));
            }
            else if ((Enums.ContentType)item.ContentType == Enums.ContentType.Website)
            {
                ItemWebsite website = new ItemWebsite(new Guid(item.ItemGuidID));
                AssembleTableRow(sb, "<b>网站小资料</b>");
                if (website.WebsiteUrl.Length > 0)
                    AssembleTableRow(sb, "网址：" + website.WebsiteUrl);
                if (website.AdminName.Length > 0)
                    AssembleTableRow(sb, "管理员：" + website.AdminName);
            }
            else if ((Enums.ContentType)item.ContentType == Enums.ContentType.Magazine)
            {
                ItemMagazine magazine = new ItemMagazine(new Guid(item.ItemGuidID));
                AssembleTableRow(sb, "<b>杂志小资料</b>");
                if (magazine.PublishedYear > 0)
                    AssembleTableRow(sb, string.Concat("发行日期：", magazine.PublishedYear, 
                        magazine.PublishedMonth > 0 ? "/"+magazine.PublishedMonth : "?",
                        magazine.PublishedDay > 0 ? "/"+magazine.PublishedDay : "?"));
                if (magazine.Editor != null && magazine.Editor.Length > 0)
                    AssembleTableRow(sb, "主编：" + magazine.Editor);
                if (magazine.Price != null && magazine.Price.Length > 0)
                    AssembleTableRow(sb, "定价：" + magazine.Price);
            }
            else if ((Enums.ContentType)item.ContentType == Enums.ContentType.Essay)
            {
                ItemEssay essay = new ItemEssay(new Guid(item.ItemGuidID));
                AssembleTableRow(sb, "<b>小资料</b>");
                if (essay.Author != null && essay.Author.Length > 0)
                {
                    PublishType pt = new PublishType(essay.PublishTypeID);
                    AssembleTableRow(sb, pt.PublishTypeName + "/" + essay.Author);
                }
                if (essay.OriginalAuthor != null && essay.OriginalAuthor.Length > 0)
                    AssembleTableRow(sb, "原作者：" + essay.OriginalAuthor);
                if (essay.PublishedYear > 0)
                    AssembleTableRow(sb, string.Concat("日期：", essay.PublishedYear,
                        essay.PublishedMonth > 0 ? "/" + essay.PublishedMonth : "?",
                        essay.PublishedDay > 0 ? "/" + essay.PublishedDay : "?"));
                if (essay.AppearAt != null && essay.AppearAt.Length > 0)
                    AssembleTableRow(sb, "自：" + essay.AppearAt);
            }
            else
            {
                AssembleTableRow(sb, "<b>小资料</b>");
                AssembleTableRow(sb, "暂无");
            }
            sb.AppendLine("</table>");
            sb.AppendLine("<br><br>");
            sb.AppendLine("</div>");

            return sb.ToString();
        }

        string DisplayCharactorsAndWorks(Item item)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("<hr size=1>");
            if ((Enums.ContentType)item.ContentType == Enums.ContentType.Author)
            {
                sb.AppendLine("<div><b>笔下人物</b>");
                sb.AppendLine("<div>");
                ItemPerson person = new ItemPerson(new Guid(item.ItemGuidID));
                //check if this person has related person type content
                List<Item> relatedItems = Item.RelatedItemCollection(item.ItemGuidID);
                foreach (Item i in relatedItems)
                {
                    if ((Enums.ContentType)i.ContentType == Enums.ContentType.Author)
                    {
                        sb.AppendLine("<p><a href=javascript:void(0); onclick=\"window.external.LoadItem('" + i.ItemGuidID + "')\">" + i.Title + "</a></p>");
                    }
                }
                sb.AppendLine("</div></div>");
            }

            return sb.ToString();
        }

        string DisplayRelatedItem(Item item)
        {
            List<Item> relatedItems = Item.RelatedItemCollection(item.ItemGuidID);
            if (relatedItems.Count == 0) return string.Empty;

            StringBuilder sb = new StringBuilder();
            sb.AppendLine("<hr size=1>");
            sb.AppendLine("<div><b>相关条目</b>");
            sb.AppendLine("<div>");
            foreach (Item i in relatedItems)
                sb.AppendLine("<p><a href=javascript:void(0); onclick=\"window.external.LoadItem('" + i.ItemGuidID + "')\">" + i.Title + "</a></p>");
            sb.AppendLine("</div></div>");
            return sb.ToString();
        }

        void AssembleTableRow(StringBuilder sb, string msg)
        {
            sb.AppendLine(string.Concat("<tr><td>", msg, "</td></tr>"));
        }

        public void PrintPreview()
        {
            if (webBrowser1 == null) return;
            webBrowser1.ShowPrintPreviewDialog();
        }

        public Panel DockablePanel
        {
            get { return panel1; }
            set { panel1 = value; }
        }

        private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            //System.Diagnostics.Debug.WriteLine(e.Url);
        }
    }
}